
#include "abs-time.h"

#include <stdlib.h>
#include <sys/time.h>

namespace dulymoo {

ABSTime::ABSTime()
{
    Now();
}

ABSTime::ABSTime(unsigned long seconds, unsigned long useconds) :
    seconds_(seconds), useconds_(useconds)
{
}

ABSTime::ABSTime(const ABSTime &time) :
    seconds_(time.seconds_), useconds_(time.useconds_)
{
}

ABSTime& ABSTime::operator= (const ABSTime &time)
{
    seconds_  = time.seconds_;
    useconds_ = time.useconds_;
}

bool ABSTime::operator<  (const ABSTime &time) const
{
    return seconds_ < time.seconds_ ? true :
           seconds_ > time.seconds_ ? false :
           useconds_ < time.useconds_;
}

bool ABSTime::operator<= (const ABSTime &time) const
{
    return !(time < *this);
}

bool ABSTime::operator>  (const ABSTime &time) const
{
    return time < *this;
}

bool ABSTime::operator>= (const ABSTime &time) const
{
    return !(*this < time);
}

bool ABSTime::operator== (const ABSTime &time) const
{
    return seconds_ == time.seconds_ && useconds_ == time.useconds_;
}

bool ABSTime::operator!= (const ABSTime &time) const
{
    return !(*this == time);
}

ABSTime& ABSTime::Now()
{
    struct timeval now;
    gettimeofday(&now, NULL);
    seconds_  = now.tv_sec;
    useconds_ = now.tv_usec;
    return *this;
}

ABSTime& ABSTime::Adjust(long seconds, long useconds)
{
    const long kMillion = 1000 * 1000;

    seconds += seconds_;
    useconds += useconds_;

    if (useconds < 0)
    {
        long sec_adjustment = (-useconds) / kMillion + 1;
        seconds  -= sec_adjustment;
        useconds += sec_adjustment * kMillion;
    }

    if (useconds >= kMillion)
    {
        seconds += useconds / kMillion;
        useconds = useconds % kMillion;
    }

    if (seconds >= 0)
    {
        seconds_  = seconds;
        useconds_ = useconds;
    }

    return *this;
}

}  // namespace dulymoo

